/**
 * 文件名称: user_freetype.c
 * 摘    要: 与freetype相关的操作函数源文件
 * 来    源: huenrong
 *
 * 当前版本: 1.0 
 * 作    者: huenrong
 * 完成日期: 2019-08-01
 **/

#include <stdio.h>
#include <math.h>

#include "user_freetype.h"
#include "../framebuffer/framebuffer.h"

static FT_Face face;       // handle to face object

/******************************************************************************
函数名称: freetype_init
函数功能: freetype初始化
函数参数: font_file_path: 字体文件路径
函数返回: 无
******************************************************************************/
void freetype_init(const char *font_file_path)
{
    FT_Error error = -1;
    FT_Library library = {0};       // handle to library
    
    // initialize the library
    error = FT_Init_FreeType(&library);
    if (error)
    {
        printf("freetype_init FT_Init_FreeType error\r\n");
    }
    
    // create face object(load a font face from a font file)
    error = FT_New_Face(library, font_file_path, 0, &face);
    if (FT_Err_Unknown_File_Format == error)
    {
        printf("freetype_init unsupported font format\r\n");
    }
    else if (error)
    {
        printf("freetype_init open font file error\r\n");
    }
}

/******************************************************************************
函数名称: freetype_set_pixel_size
函数功能: freetype设置字体像素大小(某一维度值为0, 则和另一维度相同)
函数参数: pixel_width: 字体像素宽度
          pixel_height: 字体像素高度
函数返回: 成功: 返回0
          失败: 返回错误码
******************************************************************************/
int freetype_set_pixel_size(const unsigned int pixel_width, 
                            const unsigned int pixel_height)
{
    FT_Error error = -1;

    error = FT_Set_Pixel_Sizes(face, pixel_width, pixel_height);

    return error;
}

/******************************************************************************
函数名称: freetype_display_str
函数功能: freetype显示字符串
函数参数: x_start: 第一个字符显示的x轴起始坐标
          y_start: 第一个字符显示的y轴起始坐标
          angle: 字符旋转角度
          show_str: 要显示的字符串
          str_len: 字符串长度
          background_color: 字符背景色
          foreground: 字符前景色
函数返回: 无
******************************************************************************/
void freetype_display_str(FT_Int x_start, FT_Int y_start, const char *angle, 
                          const wchar_t *show_str, const unsigned int str_len, 
                          const unsigned int background_color, 
                          const unsigned int foreground)
{
    FT_Error error = -1;
    FT_Vector pen = {0};
    FT_Matrix matrix = {0};
    FT_GlyphSlot slot = {0};
    double matrix_angle = 0.0;
    FT_Int x = 0, y = 0;        // 当前显示的x/y坐标
    FT_Int index_x = 0, index_y = 0;    // 位图数据索引
    unsigned int color = 0;     // 显示颜色

    slot = face->glyph;

    /* 确定坐标:
	 * lcd_x = var.xres/2 + 8 + 16
	 * lcd_y = var.yres/2 + 16
	 * 笛卡尔座标系:
	 * x = lcd_x = var.xres/2 + 8 + 16
	 * y = var.yres - lcd_y = var.yres/2 - 16
	 */
	pen.x = (SCREEN_WIDTH/2 + 8 + 16) * 64;
	pen.y = (SCREEN_HEIGHT/2 - 16) * 64;
 
	matrix_angle = (1.0 * strtoul(angle, NULL, 0) / 360) * 3.14159 * 2;
	/* set up matrix */
	matrix.xx = (FT_Fixed)(cos( matrix_angle ) * 0x10000L);
	matrix.xy = (FT_Fixed)(-sin( matrix_angle ) * 0x10000L);
	matrix.yx = (FT_Fixed)(sin( matrix_angle ) * 0x10000L);
	matrix.yy = (FT_Fixed)(cos( matrix_angle ) * 0x10000L);

    for (int i=0; i<str_len; i++)
    {
        // set transformation
        FT_Set_Transform(face, &matrix, &pen);
        
        // load glyph image into the slot (erase previous one)
        error = FT_Load_Char(face, show_str[i], FT_LOAD_RENDER);

        // 绘制字形图到屏幕
        for (x=x_start, index_x=0; x<(x_start + slot->bitmap.width); x++, index_x++)
        {
            for (y=y_start, index_y=0; y<(y_start + slot->bitmap.rows); y++, index_y++)
            {
                // 从数据中获取对应像素点的颜色码
                color = slot->bitmap.buffer[index_y * slot->bitmap.width + index_x];
                if (BLACK == color)     // 要显示的是背景色
                {
                    color = background_color;
                }
                else    // 要显示的是前景色
                {
                    color = foreground;
                }
                framebuffer_draw_point(x, y, color);        // 显示当前坐标的颜色
            }
        }

        // 显示起点移动到下一个字符的位置
        x_start += slot->bitmap.width;
        y_start += 0;
    }
}

